package modeller.databasedesignmodel;

import exceptions.RelationAlreadyInSetException;
import exceptions.TransactionAlreadyInSetException;
import modeller.databasedesignmodel.relation.Relation;
import modeller.databasedesignmodel.transaction.Transaction;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: Jason Ye
 * Date: 22/01/2012
 * Time: 16:04
 * A class to encapsulate a database design which is used as input into the modeller actual.
 */
public class DatabaseDesign implements Serializable {


    /**
     * default empty constructor
     */
    public DatabaseDesign() {

    }

    public DatabaseDesign(HashSet<Transaction> transactions,HashSet<Relation> relations,double DBPageSize,double averageIOTime,double DBFillFactor){
        this.transactions=transactions;
        this.relations=relations;
        this.DBPageSize=DBPageSize;
        this.averageIOTime=averageIOTime;
        this.DBFillFactor=DBFillFactor;
    }

    /**
     * private member variables
     */
    private HashSet<Transaction> transactions = new HashSet<Transaction>();
    private HashSet<Relation> relations = new HashSet<Relation>();
    private double DBPageSize;

    private double averageIOTime;
    private double DBFillFactor;

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();

        buf.append("Database Design:"
                    +"\n\tDB Page Size: " + DBPageSize
                    +"\n\tDB Fill Factor: "+DBFillFactor);

        buf.append("\n************* RELATIONS *************\n");
        
        for(Relation rel:relations){
            buf.append("\n"+rel.toString()+"\n");
        }

        buf.append("\n********** END OF RELATIONS **********");

        buf.append("\n************ TRANSACTIONS ************\n");

        for(Transaction t: transactions){
            buf.append("\n"+t.toString()+"\n");
        }

        return buf.toString();

    }

    /**
     * adds a transaction to the DB design
     *
     * @param toAdd
     * @throws exceptions.TransactionAlreadyInSetException
     *
     */
    public void addTransaction(Transaction toAdd) throws TransactionAlreadyInSetException {

        if (transactions.contains(toAdd)) {
            throw new TransactionAlreadyInSetException();
        } else {
            transactions.add(toAdd);
        }
    }

    /**
     * removes a given relation from the DB design
     *
     * @param toRemove
     */
    public void removeTransaction(Transaction toRemove) {

        transactions.remove(toRemove);

    }

    /**
     * adds a new relation to the database design
     *
     * @param toAdd
     * @throws exceptions.RelationAlreadyInSetException
     *
     */
    public void addRelation(Relation toAdd) throws RelationAlreadyInSetException {

        if (relations.contains(toAdd)) {
            throw new RelationAlreadyInSetException();
        } else {
            relations.add(toAdd);
        }
    }

    /**
     * removes a transaction from the given DB design
     *
     * @param toRemove
     */
    public void removeTransaction(Relation toRemove) {

        relations.remove(toRemove);
    }

    public HashSet<Transaction> getTransactions() {
        return transactions;
    }


    public HashSet<Relation> getRelations() {
        return relations;
    }

    public double getDBPageSize() {
        return DBPageSize;
    }

    public void setDBPageSize(int DBPageSize) {
        this.DBPageSize = DBPageSize;
    }

    public double getDBFillFactor() {
        return DBFillFactor;
    }

    public void setDBFillFactor(double DBFillFactor) {
        this.DBFillFactor = DBFillFactor;
    }

    public void setTransactions(HashSet<Transaction> transactions) {
        this.transactions = transactions;
    }

    public void setRelations(HashSet<Relation> relations) {

        this.relations = relations;
    }

    public double getDAverageIOTime() {
        return averageIOTime;
    }

    public void setDAverageIOTime(double ioTime) {
        averageIOTime=ioTime;
    }
}
